#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <string.h>

#if 1   // 开启DEBUG打印
#define LOGD(...) { printf(__VA_ARGS__); fflush(stdout); }
#else   // 关闭DEBUG打印
#define LOGD(...)
#endif

#if 1   // 开启ERROR打印
#define LOGE(...) { printf(__VA_ARGS__); fflush(stdout); }
#else   // 关闭ERROR打印
#define LOGE(...)
#endif

#define BUF_SIZE    2048
#define EXIT_STR    "exit"
#define I_EXIT      "I exit.\r\n"
#define I_RECEIVE   "I receive.\r\n"

// 打开串口
HANDLE OpenSerial(const char *com, int baud, int byteSize, int parity, int stopBits) {
    DCB dcb;
    BOOL b = FALSE;
    COMMTIMEOUTS CommTimeouts;
    HANDLE comHandle = INVALID_HANDLE_VALUE;

    // 打开串口
    comHandle = CreateFile(com, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (INVALID_HANDLE_VALUE == comHandle) {
        LOGE("CreateFile fail\r\n");
        return comHandle;
    }

    // 设置读写缓存大小
    b = SetupComm(comHandle, BUF_SIZE, BUF_SIZE);
    if (!b) {
        LOGE("SetupComm fail\r\n");
    }

    // 设定读写超时
    CommTimeouts.ReadIntervalTimeout = MAXDWORD;
    CommTimeouts.ReadTotalTimeoutMultiplier = 0;
    CommTimeouts.ReadTotalTimeoutConstant = 0;
    CommTimeouts.WriteTotalTimeoutMultiplier = 1;
    CommTimeouts.WriteTotalTimeoutConstant = 1;
    b = SetCommTimeouts(comHandle, &CommTimeouts);
    if (!b) {
        LOGE("SetCommTimeouts fail\r\n");
    }

    // 设置串口状态属性
    GetCommState(comHandle, &dcb);
    dcb.BaudRate = baud;
    dcb.ByteSize = byteSize;
    dcb.Parity   = parity;
    dcb.StopBits = stopBits;
    b = SetCommState(comHandle, &dcb);
    if (!b) {
        LOGE("SetCommState fail\r\n");
    }

    return comHandle;
}

// 封装为一个方法供JNA调用
__declspec(dllexport) void startSerialCommunication(const char *com) {
    BOOL b = FALSE;
    DWORD wRLen = 0;
    DWORD wWLen = 0;
    char buf[BUF_SIZE] = {0};
    HANDLE comHandle = INVALID_HANDLE_VALUE;

    // 打开串口
    comHandle = OpenSerial(com, CBR_9600, 8, NOPARITY, ONE5STOPBITS);
    if (INVALID_HANDLE_VALUE == comHandle) {
        LOGE("OpenSerial COM fail!\r\n");
        return;
    }
    LOGD("Open COM Successfully!\r\n");

    while (1) {
        wRLen = 0;
        time_t old_time = time(NULL);
        b = ReadFile(comHandle, buf, sizeof(buf)-1, &wRLen, NULL);
        time_t end_time = time(NULL);
        if (b && 0 < wRLen) {
            buf[wRLen] = '\0';
            LOGE("<<< TIME:%d \n>>>",end_time-old_time);
            LOGD("[RECV]%s\r\n", buf);
            // 对buf数据进行处理
            if (0 == strncmp(buf, EXIT_STR, strlen(EXIT_STR))) {
                b = WriteFile(comHandle, TEXT(I_EXIT), strlen(I_EXIT), &wWLen, NULL);
                if (!b) {
                    LOGE("WriteFile fail\r\n");
                }
                break;
            }
            b = WriteFile(comHandle, TEXT(I_RECEIVE), strlen(I_RECEIVE), &wWLen, NULL);
            if (!b) {
                LOGE("WriteFile fail\r\n");
            }
        }
    }

    // 关闭串口
    b = CloseHandle(comHandle);
    if (!b) {
        LOGE("CloseHandle fail\r\n");
    }

    LOGD("Program Exit.\r\n");
}
